/**
 * 
 */
package org.paybiz.core.payplatform.yeePay.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paybiz.constant.PayConstant;
import org.paybiz.core.payplatform.yeePay.bean.YeeBackResultDO;
import org.paybiz.core.payplatform.yeePay.bean.YeePayDO;
import org.paybiz.core.payplatform.yeePay.bean.YeeQueryResultDO;
import org.paybiz.core.payplatform.yeePay.constant.YeepayConstant;
import org.paybiz.core.payplatform.yeePay.util.DigestUtil;
import org.paybiz.core.payplatform.yeePay.util.HttpUtils;
import org.paybiz.core.service.pay.PayService;
import org.paybiz.model.PayModel;
import org.paybiz.model.PayReqResultDO;
import org.paybiz.util.DynamicConfig;
import org.paybiz.util.PaySignUtil;
import org.paybiz.util.TranslateUtil;
import org.springframework.stereotype.Service;

/**
 * @Title: YeePayServiceImpl.java
 * @Description: 易宝支付实现类
 * @author Nassir.wen
 * @date 2010-10-14 上午10:54:14
 * @version V1.0
 * @Company: MSD.
 * @Copyright Copyright (c) 2010
 */
@Service("yeePayService")
public class YeePayServiceImpl implements PayService {

    // 日志对象
    private static final Log logger = LogFactory.getLog(YeePayServiceImpl.class);
    // 内部密钥
    private static String msdValue = "";
    // 商户编号
    private static String p1_MerId = "";
    // 商户密钥
    private static String keyValue = "";

    // 支付请求地址
    private static String yeepayCommonReqURL = "";

    // 易宝支付回调链接
    private static String yeepayCallBackURL = "";

    // 易宝支付查询链接
    private static String yeepayQueryRefundReqURL = "";

    /**
     * 构造方法
     */
    public YeePayServiceImpl() {
        // 通过资源文件获取
        msdValue = DynamicConfig.getInstance().getValue(PayConstant.PAY_BIZ_KEY);
        p1_MerId = DynamicConfig.getInstance().getValue(YeepayConstant.P1_MERID);
        keyValue = DynamicConfig.getInstance().getValue(YeepayConstant.KEYVALUE);
        yeepayCommonReqURL = DynamicConfig.getInstance().getValue(YeepayConstant.YEEPAY_COMMONREQURL);
        yeepayCallBackURL = DynamicConfig.getInstance().getValue(YeepayConstant.YEEPAY_CALLBACKURL);
        yeepayQueryRefundReqURL = DynamicConfig.getInstance().getValue(YeepayConstant.YEEPAY_QUERYURL);
    }

    public PayReqResultDO pay(PayModel payDO) {
        PayReqResultDO payReqResultDO = new PayReqResultDO();// 内部支付结果对象
        YeePayDO yeePayDO = getYeePayDO(payDO);
        // 获取支付链接
        String payURL = getReqMd5HmacForOnlinePayment(yeePayDO);
        payReqResultDO.setResult(0);
        payReqResultDO.setErrMsg("");
        payReqResultDO.setErrId("");
        payReqResultDO.setPayUrl(payURL);
        payReqResultDO.setHmac(PaySignUtil.getPayReqResultDOHmac(payReqResultDO, msdValue));
        return payReqResultDO;
    }

    private String getReqMd5HmacForOnlinePayment(YeePayDO yeePayDO) {
        StringBuffer reqUrl = new StringBuffer(yeepayCommonReqURL);
        StringBuffer parameters = new StringBuffer();
        parameters.append(getParam(YeepayConstant.P0_CMD, yeePayDO.getP0_Cmd()))
                .append(getParam(YeepayConstant.P1_MERID, yeePayDO.getP1_MerId()))
                .append(getParam(YeepayConstant.P2_ORDER, yeePayDO.getP2_Order()))
                .append(getParam(YeepayConstant.P3_AMT, yeePayDO.getP3_Amt()))
                .append(getParam(YeepayConstant.P4_CUR, yeePayDO.getP4_Cur()))
                .append(getParam(YeepayConstant.P5_PID, yeePayDO.getP5_Pid()))
                .append(getParam(YeepayConstant.P6_PCAT, yeePayDO.getP6_Pcat()))
                .append(getParam(YeepayConstant.P7_PDESC, yeePayDO.getP7_Pdesc()))
                .append(getParam(YeepayConstant.P8_URL, yeePayDO.getP8_Url()))
                .append(getParam(YeepayConstant.P9_SAF, yeePayDO.getP9_SAF()))
                .append(getParam(YeepayConstant.PA_MP, yeePayDO.getPa_MP()))
                .append(getParam(YeepayConstant.PD_FRPID, yeePayDO.getPd_FrpId()))
                .append(getParam(YeepayConstant.PR_NEEDRESPONSE, yeePayDO.getPr_NeedResponse()));

        String hmac = getHmac(yeePayDO, keyValue);
        parameters.append(getParam(YeepayConstant.HMAC, hmac));
        // 支付链接与参数拼接
        if (reqUrl.indexOf("?") == -1) {
            reqUrl.append("?").append(parameters);
        } else {
            reqUrl.append("&").append(parameters);
        }
        // 去除链接最后的"&"
        String strURL = reqUrl.toString();
        if (YeepayConstant.URL_PARAM_CONNECT_FLAG.equals("" + strURL.charAt(strURL.length() - 1))) {
            strURL = strURL.substring(0, strURL.length() - 1);
        }
        return strURL;
    }

    /**
     * 参数构造
     * 
     * @param param
     * @param value
     * @return
     */
    private StringBuilder getParam(String param, String value) {
        StringBuilder p = new StringBuilder();
        String str = value != null ? value.toString() : "";
        try {
            // 运用URLEncoder编码
            str = URLEncoder.encode(str, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        p.append(param).append("=").append(str).append(YeepayConstant.URL_PARAM_CONNECT_FLAG);
        return p;
    }

    /**
     * 获取支付签名
     * 
     * @param yeePay
     *            易宝支付对象
     * @param keyValue
     *            商户密钥
     */
    private String getHmac(YeePayDO yeePay, String keyValue) {
        StringBuffer sValue = new StringBuffer();
        sValue.append(yeePay.getP0_Cmd()).append(yeePay.getP1_MerId()).append(yeePay.getP2_Order())
                .append(yeePay.getP3_Amt()).append(yeePay.getP4_Cur()).append(yeePay.getP5_Pid())
                .append(yeePay.getP6_Pcat()).append(yeePay.getP7_Pdesc()).append(yeePay.getP8_Url())
                .append(yeePay.getP9_SAF()).append(yeePay.getPa_MP()).append(yeePay.getPd_FrpId())
                .append(yeePay.getPr_NeedResponse());
        String hmac = null;
        hmac = DigestUtil.hmacSign(sValue.toString(), keyValue);
        return hmac;
    }

    /**
     * 构造易宝支付参数对象
     * 
     * @param payDO
     * @return
     */
    private YeePayDO getYeePayDO(PayModel payDO) {
        YeePayDO yeePayDO = new YeePayDO();
        yeePayDO.setP0_Cmd("Buy");
        //1为公司账户、0为私人账户
        yeePayDO.setP1_MerId(p1_MerId);
        yeePayDO.setP2_Order(payDO.getOrderId());
        yeePayDO.setP3_Amt(TranslateUtil.getFen2Yuan(payDO.getPayMoney()));
        yeePayDO.setP4_Cur("CNY");
        yeePayDO.setP5_Pid(payDO.getSubject());
        yeePayDO.setP6_Pcat(payDO.getCategory());
        yeePayDO.setP7_Pdesc(payDO.getBody());
        yeePayDO.setP8_Url(StringUtils.isNotEmpty(payDO.getSynCallbackUrl()) ? payDO.getSynCallbackUrl()
                : yeepayCallBackURL);
        yeePayDO.setP9_SAF("0");// 用户收货地址是否需要保存在易宝 1需要 0不需要 默认 0
        yeePayDO.setPa_MP(payDO.getResultUrl() + "&sign=" + payDO.getSign());// 交易结果显示链接
        //		int payType = payDO.getPayType();
        //		int flag = payDO.getFlag();
        //		
        //		//充值使用易宝银行直联 payType 10 以上的为银行代码
        //		if(flag == PaymentConstant.PAYMENT_ADDFUNDS && payType > 10 && payType < 1001) {
        //		    logger.info("易宝银行直连充值...");
        //		    String bankCode = BankCodeConfig.getInstance().getBankCode(payType+"", ConstantPay.YEEPAY);
        //		    yeePayDO.setPd_FrpId(bankCode);
        //		}else if(flag == PaymentConstant.PAYMENT_ADDFUNDS 
        //		        && (RechargeCardConstant.getRechargeCardTypeEnum(payType) != null)) {
        //		    //充值充值直连
        //		    yeePayDO.setPd_FrpId(RechargeCardConstant.getRechargeCardTypeEnum(payType).name());
        //		}
        yeePayDO.setPr_NeedResponse("1");
        return yeePayDO;
    }

    public static boolean verifyCallback(YeeBackResultDO resultDO, Integer sign) {
        // TODO Auto-generated method stub
        StringBuilder sValue = new StringBuilder();
        sValue.append(p1_MerId);
        // 业务类型
        sValue.append(resultDO.getR0_Cmd());
        // 支付结果
        sValue.append(resultDO.getR1_Code());
        // 易宝支付交易流水号
        sValue.append(resultDO.getR2_TrxId());
        // 支付金额
        sValue.append(resultDO.getR3_Amt());
        // 交易币种
        sValue.append(resultDO.getR4_Cur());
        // 商品名称
        sValue.append(resultDO.getR5_Pid());
        // 商户订单号
        sValue.append(resultDO.getR6_Order());
        // 易宝支付会员ID
        sValue.append(resultDO.getR7_Uid());
        // 商户扩展信息
        sValue.append(resultDO.getR8_MP());
        // 交易结果返回类型
        sValue.append(resultDO.getR9_BType());
        String sNewString = null;
        sNewString = DigestUtil.hmacSign(sValue.toString(), keyValue);
        if (resultDO.getHmac().equals(sNewString)) {
            return (true);
        }
        return (false);
    }

    /**
     * 易宝支付结果查询
     * 
     * @param orderId
     *            支付请求参数p2_Order
     * @param tag 
     * 		0为私人账户、1为公司账户
     * @return -1 未支付   0  支付失败   1 支付成功  2异常情况 
     * 
     */
    @Override
    public int autoCheckOrder(String orderId, Date date, Integer tag) {
        YeeQueryResultDO qr = new YeeQueryResultDO();
        String hmac = DigestUtil.getHmac(new String[] { YeepayConstant.YEEPAY_QUERY_CMD, p1_MerId, orderId }, keyValue);
        Map<String, Object> reParams = new HashMap<String, Object>();
        reParams.put("p0_Cmd", YeepayConstant.YEEPAY_QUERY_CMD);
        reParams.put("p1_MerId", p1_MerId);
        reParams.put("p2_Order", orderId);
        reParams.put("hmac", hmac);
        List responseStr = null;
        try {
            if (logger.isInfoEnabled()) {
                logger.info("自动对账开始请求参数[" + reParams + "]");
            }
            responseStr = HttpUtils.URLGet(yeepayQueryRefundReqURL, reParams);
            if (logger.isInfoEnabled()) {
                logger.info("自动对账结束请求返回参数[" + responseStr + "]");
            }
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                logger.error("自动对账请求失败", e);
            }
            //查询异常
            return 2;
        }
        if (responseStr.size() == 0) {
            if (logger.isErrorEnabled()) {
                logger.error("自动对账服务器无法响应");
            }
            //查询异常
            return 2;
        }
        for (int t = 0; t < responseStr.size(); t++) {
            String currentResult = (String) responseStr.get(t);
            if (currentResult == null || currentResult.equals("")) {
                continue;
            }
            try {
                currentResult = URLDecoder.decode(currentResult, "GBK");
            } catch (UnsupportedEncodingException e) {
                if (logger.isErrorEnabled()) {
                    logger.error("不支持的编码格式", e);
                }
                continue;
            }
            int i = currentResult.indexOf("=");
            if (i >= 0) {
                String sKey = currentResult.substring(0, i);
                String sValue = currentResult.substring(i + 1);
                if (sKey.equals("r0_Cmd")) {
                    qr.setR0_Cmd(sValue);
                } else if (sKey.equals("r1_Code")) {
                    qr.setR1_Code(sValue);
                } else if (sKey.equals("r2_TrxId")) {
                    qr.setR2_TrxId(sValue);
                } else if (sKey.equals("r3_Amt")) {
                    qr.setR3_Amt(sValue);
                } else if (sKey.equals("r4_Cur")) {
                    qr.setR4_Cur(sValue);
                } else if (sKey.equals("r5_Pid")) {
                    qr.setR5_Pid(sValue);
                } else if (sKey.equals("r6_Order")) {
                    qr.setR6_Order(sValue);
                } else if (sKey.equals("r8_MP")) {
                    qr.setR8_MP(sValue);
                } else if (sKey.equals("rb_PayStatus")) {
                    qr.setRb_PayStatus(sValue);
                } else if (sKey.equals("rc_RefundCount")) {
                    qr.setRc_RefundCount(sValue);
                } else if (sKey.equals("rd_RefundAmt")) {
                    qr.setRd_RefundAmt(sValue);
                } else if (sKey.equals("hmac")) {
                    qr.setHmac(sValue);
                }
            }
        }
        String newHmac = getYeeQueryResultDO(qr, keyValue);
        if (!newHmac.equals(qr.getHmac())) {
            if (logger.isInfoEnabled()) {
                logger.info("易宝查询签名失败,易宝签名:" + qr.getHmac() + "本地签名:" + newHmac);
            }
            //查询异常,签名错误
            return 2;
        }
        if (qr.getR1_Code().equals("1")) {
            if (logger.isErrorEnabled()) {
                logger.error("易宝查询正常查询状态：1");
            }
        }
        //订单不存在
        if ("50".equals(qr.getR1_Code())) {
            if (logger.isInfoEnabled()) {
                logger.info("自动对账订单ID:" + orderId + " 易宝订单不存在!");
            }
            //未支付
            return -1;
        }
        String status = qr.getRb_PayStatus();
        logger.info("易宝查询返回状态：" + status + " 注：SUCCESS 成功,INIT 未支付,CANCELED 已取消");
        if ("SUCCESS".equals(status)) {
            if (logger.isInfoEnabled()) {
                logger.info("自动对账订单ID:" + orderId + " 易宝已支付成功!");
            }
            return 1;
        } else if ("INIT".equals(status)) {
            if (logger.isInfoEnabled()) {
                logger.info("自动对账订单ID:" + orderId + " 易宝未支付!");
            }
            return -1;
        } else if ("CANCELED".equals(status)) {
            if (logger.isInfoEnabled()) {
                logger.info("自动对账订单ID:" + orderId + " 在易宝支付已取消");
            }
            //已取消,作为支付失败处理
            return 0;
        }
        return -1;
    }

    /**
     * 返回结果查询结果签名
     * 
     * @param qr
     * @param keyValue
     * @return
     */
    private String getYeeQueryResultDO(YeeQueryResultDO qr, String keyValue) {
        StringBuilder sValue = new StringBuilder();
        sValue.append(qr.getR0_Cmd()).append(qr.getR1_Code()).append(qr.getR2_TrxId()).append(qr.getR3_Amt())
                .append(qr.getR4_Cur()).append(qr.getR5_Pid()).append(qr.getR6_Order()).append(qr.getR8_MP())
                .append(qr.getRb_PayStatus()).append(qr.getRc_RefundCount()).append(qr.getRd_RefundAmt());
        String hmac = DigestUtil.hmacSign(sValue.toString(), keyValue);
        return hmac;
    }

}
